﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHTools.Tools;
using NHibernate;

namespace NHTools.Base
{
    [Serializable]
    public class NHBase<T> : NHEntityBase
    {
        #region Static Properties and Methods

        private static Context<T> _Context;

        public static Context<T> Context
        {
            get
            {
                if (NHBase<T>._Context == null || !PersistenceSession.IsOpen)
                    NHBase<T>._Context = new Context<T>(PersistenceSession);
                return NHBase<T>._Context;
            }
            set { NHBase<T>._Context = value; }
        }

        public static List<T> GetAll()
        {
            return Context.Linq.ToList();
        }

        public static T GetById(int Id)
        {
            return PersistenceSession.Get<T>(Id);
        }

        public static T Save(T NHObject)
        {
            if (NHObject == null)
                return default(T);

            if ((NHObject as NHEntityBase).Id == 0)
                (NHObject as NHEntityBase).CreatedDate = DateTime.Now;
            (NHObject as NHEntityBase).ModifiedDate = DateTime.Now;
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Save(NHObject);
                PersistenceSession.Flush();
                trns.Commit();
                return NHObject;
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
                return default(T);
            }
        }

        public static void Save(List<T> NHObject)
        {
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                foreach (var item in NHObject)
                {
                    if (item != null)
                    {
                        if ((item as NHEntityBase).Id == 0)
                            (item as NHEntityBase).CreatedDate = DateTime.Now;
                        (item as NHEntityBase).ModifiedDate = DateTime.Now;
                        PersistenceSession.Save(item);
                    }
                }
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static void Save(IList<T> NHObject)
        {
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                foreach (var item in NHObject)
                {
                    if (item != null)
                    {
                        if ((item as NHEntityBase).Id == 0)
                            (item as NHEntityBase).CreatedDate = DateTime.Now;
                        (item as NHEntityBase).ModifiedDate = DateTime.Now;
                        PersistenceSession.Save(item);
                    }
                }
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static T Update(T NHObject)
        {
            if (NHObject == null)
                return default(T);

            if ((NHObject as NHEntityBase).Id == 0)
                (NHObject as NHEntityBase).CreatedDate = DateTime.Now;
            (NHObject as NHEntityBase).ModifiedDate = DateTime.Now;
            // ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Update(NHObject);
                PersistenceSession.Flush();
                //trns.Commit();
                return NHObject;
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                //trns.Rollback();
                throw ex;
                return default(T);
            }
        }

        public static void Update(List<T> NHObject)
        {
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                foreach (var item in NHObject)
                {
                    if (item != null)
                    {
                        if ((item as NHEntityBase).Id == 0)
                            (item as NHEntityBase).CreatedDate = DateTime.Now;
                        (item as NHEntityBase).ModifiedDate = DateTime.Now;
                        PersistenceSession.Update(item);
                    }
                }
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static void Update(IList<T> NHObject)
        {
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                foreach (var item in NHObject)
                {
                    if (item != null)
                    {
                        if ((item as NHEntityBase).Id == 0)
                            (item as NHEntityBase).CreatedDate = DateTime.Now;
                        (item as NHEntityBase).ModifiedDate = DateTime.Now;
                        PersistenceSession.Update(item);
                    }
                }
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static void Delete(int id)
        {
            T NHObject = GetById(id);
            if (NHObject == null)
                return;
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Delete(NHObject);
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static void Delete(T NHObject)
        {
            if (NHObject == null)
                return;
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Delete(NHObject);
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        public static void Delete(List<T> NHObject)
        {
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                foreach (var item in NHObject)
                {
                    if (NHObject != null)
                        PersistenceSession.Delete(item);
                }
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(typeof(T).Name, ex);
                trns.Rollback();
                throw ex;
            }
        }

        #endregion

        public virtual T Copy()
        {
            return (T)this.MemberwiseClone();
        }

        public virtual T Clone()
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bf.Serialize(ms, this);
            ms.Close();
            byte[] hede = ms.GetBuffer();
            System.IO.MemoryStream ms1 = new System.IO.MemoryStream(hede);
            T CloneObj = (T)bf.Deserialize(ms1);
            ms1.Close();
            return CloneObj;
        }
    }
}
